{{>header}}

import FormData from 'form-data';
import fetch, { Headers } from 'node-fetch';
import type { RequestInit, Response } from 'node-fetch';
import type { AbortSignal } from 'node-fetch/externals';

import { ApiError } from './ApiError';
import type { ApiRequestOptions } from './ApiRequestOptions';
import type { ApiResult } from './ApiResult';
import { CancelablePromise } from './CancelablePromise';
import type { OnCancel } from './CancelablePromise';
import type { OpenAPIConfig } from './OpenAPI';

{{>functions/isDefined}}


{{>functions/isString}}


{{>functions/isStringWithValue}}


{{>functions/isBlob}}


{{>functions/isFormData}}


{{>functions/base64}}


{{>functions/getQueryString}}


{{>functions/getUrl}}


{{>functions/getFormData}}


{{>functions/resolve}}


{{>node/getHeaders}}


{{>node/getRequestBody}}


{{>node/sendRequest}}


{{>node/getResponseHeader}}


{{>node/getResponseBody}}


{{>functions/catchErrorCodes}}


/**
 * Request method
 * @param config The OpenAPI configuration object
 * @param options The request options from the service
 * @returns CancelablePromise<T>
 * @throws ApiError
 */
export const request = <T>(config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise<T> => {
	return new CancelablePromise(async (resolve, reject, onCancel) => {
		try {
			const url = getUrl(config, options);
			const formData = getFormData(options);
			const body = getRequestBody(options);
			const headers = await getHeaders(config, options);

			if (!onCancel.isCancelled) {
				const response = await sendRequest(options, url, body, formData, headers, onCancel);
				const responseBody = await getResponseBody(response);
				const responseHeader = getResponseHeader(response, options.responseHeader);

				const result: ApiResult = {
					url,
					ok: response.ok,
					status: response.status,
					statusText: response.statusText,
					body: responseHeader ?? responseBody,
				};

				catchErrorCodes(options, result);

				resolve(result.body);
			}
		} catch (error) {
			reject(error);
		}
	});
};
